package org.jeecg.modules.wms.inorder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.Query;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.wms.config.WarehouseDictEnum;
import org.jeecg.modules.wms.goods.entity.WmsCargoOwners;
import org.jeecg.modules.wms.goods.entity.WmsProducts;
import org.jeecg.modules.wms.goods.mapper.WmsCargoOwnersMapper;
import org.jeecg.modules.wms.goods.service.IWmsCargoOwnersService;
import org.jeecg.modules.wms.goods.service.IWmsProductsService;
import org.jeecg.modules.wms.inorder.entity.WmsStockInOrders;
import org.jeecg.modules.wms.inorder.entity.WmsStockInOrderItems;
import org.jeecg.modules.wms.inorder.mapper.WmsStockInOrderItemsMapper;
import org.jeecg.modules.wms.inorder.mapper.WmsStockInOrdersMapper;
import org.jeecg.modules.wms.inorder.service.IWmsStockInOrderItemsService;
import org.jeecg.modules.wms.inorder.service.IWmsStockInOrdersService;
import org.jeecg.modules.wms.inorder.vo.WmsStockInOrdersPage;
import org.jeecg.modules.wms.warehouse.entity.WmsWarehouses;
import org.jeecg.modules.wms.warehouse.mapper.WmsWarehousesMapper;
import org.jeecg.modules.wms.wmstask.entity.WmsTasks;
import org.jeecg.modules.wms.wmstask.entity.WmsTasksRecords;
import org.jeecg.modules.wms.wmstask.service.IWmsTasksRecordsService;
import org.jeecg.modules.wms.wmstask.service.IWmsTasksService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Description: 入库单主表
 * @Author: jeecg-boot
 * @Date: 2025-10-27
 * @Version: V1.0
 */
@Service
public class WmsStockInOrdersServiceImpl extends ServiceImpl<WmsStockInOrdersMapper, WmsStockInOrders> implements IWmsStockInOrdersService {

    @Autowired
    private WmsStockInOrdersMapper wmsStockInOrdersMapper;
    @Autowired
    private WmsStockInOrderItemsMapper wmsStockInOrderItemsMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private WmsWarehousesMapper wmsWarehousesMapper;
    @Autowired
    private IWmsCargoOwnersService iWmsCargoOwnersService;
    @Override
    public String updateStatusPutAway(String stockInOrderId) {
        WmsStockInOrders stockInOrder = this.getById(stockInOrderId);
        String status = stockInOrder.getStatus();
        if (!WarehouseDictEnum.INBOUND_PUTAWAYING.getCode().equals(status) && !WarehouseDictEnum.INBOUND_RECEIVED.getCode().equals(status)) {
            throw new JeecgBootException("入库单状态非法");
        }
        List<WmsStockInOrderItems> oderItems = wmsStockInOrderItemsService.list(Wrappers.lambdaQuery(WmsStockInOrderItems.class)
                .eq(WmsStockInOrderItems::getOrderId, stockInOrderId));
        //获得oderItems中所有的上架数量
        int completedQuantity = oderItems.stream().mapToInt(WmsStockInOrderItems::getShelvedQuantity).sum();
        //更新已上架总量
        this.update(Wrappers.lambdaUpdate(WmsStockInOrders.class).set(WmsStockInOrders::getTotalShelvedQuantity, completedQuantity));

        //收货总数==上架总数-》收货完成
        if (stockInOrder.getTotalReceivedQuantity().equals(completedQuantity)) {
            this.update(Wrappers.lambdaUpdate(WmsStockInOrders.class).set(WmsStockInOrders::getStatus, WarehouseDictEnum.INBOUND_PUTAWAYED.getCode())
                    .eq(WmsStockInOrders::getId, stockInOrderId)
            );
        }
        return stockInOrder.getStatus();
    }

    @Override
    public String updateStatus(String stockInOrderId) {
        WmsStockInOrders stockInOrder = this.getById(stockInOrderId);
        String status = stockInOrder.getStatus();
        if (!WarehouseDictEnum.INBOUND_RECEIVING.getCode().equals(status) && !WarehouseDictEnum.INBOUND_APPROVED.getCode().equals(status)) {
            throw new JeecgBootException("入库单状态非法");
        }
        List<WmsStockInOrderItems> oderItems = wmsStockInOrderItemsService.list(Wrappers.lambdaQuery(WmsStockInOrderItems.class)
                .eq(WmsStockInOrderItems::getOrderId, stockInOrderId));
        boolean notCompleted = oderItems.stream().anyMatch(item -> !item.getStatus().equals(WarehouseDictEnum.INBOUND_DETAIL_RECEIVED.getCode()));
        if (!notCompleted){
            this.update(Wrappers.lambdaUpdate(WmsStockInOrders.class).set(WmsStockInOrders::getStatus, WarehouseDictEnum.INBOUND_RECEIVED.getCode())
                    .eq(WmsStockInOrders::getId, stockInOrderId)
            );
        }
        int totalGoodQuantity = oderItems.stream().mapToInt(WmsStockInOrderItems::getReceivedQuantity).sum();
        int totalBadQuantity = oderItems.stream().mapToInt(WmsStockInOrderItems::getDefectiveQuantity).sum();
        WmsStockInOrders newStockInOrder = this.getById(stockInOrderId);
        newStockInOrder.setTotalReceivedQuantity(totalGoodQuantity);
        newStockInOrder.setTotalDefectiveQuantity(totalBadQuantity);

        this.updateById(newStockInOrder);

        return newStockInOrder.getStatus();
    }

    /**
     * 审核--必须有入库明细才能审核通过，否则不通过
     * @param one 含有id和要修改后状态的入库单
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void audit(WmsStockInOrders one) {
        WmsStockInOrders inOrder = this.getById(one.getId());
        //只有状态为提交审核和审核失败才可以审核
        if (!WarehouseDictEnum.INBOUND_SUBMIT_AUDIT.getCode().equals(inOrder.getStatus()) && !WarehouseDictEnum.INBOUND_REJECTED.getCode().equals(inOrder.getStatus())){
            throw new JeecgBootException("入库单状态非法");
        }
        if (Objects.isNull(inOrder)){
            throw new JeecgBootException("入库单不存在");
        }
        List<WmsStockInOrderItems> items = wmsStockInOrderItemsMapper.selectList(new QueryWrapper<WmsStockInOrderItems>().eq("order_id", inOrder.getId()));
        if (items.isEmpty()){
            if (one.getStatus().equals(WarehouseDictEnum.OUTBOUND_APPROVED.getCode())){
                throw new JeecgBootException("入库单没有明细信息，不能审核通过");
            }
            inOrder.setStatus(one.getStatus());
            this.updateById(inOrder);
        }
        inOrder.setStatus(one.getStatus());
        this.updateById(inOrder);
    }

    /**
     * 提交审核
     * @param inOrder
     */
    @Override
    public void submitAudit(WmsStockInOrders inOrder) {
        //判断状态，不是初始和审核失败的不能提交
        if (!WarehouseDictEnum.INBOUND_INITIAL.getCode().equals(inOrder.getStatus()) && !WarehouseDictEnum.INBOUND_REJECTED.getCode().equals(inOrder.getStatus())) {
            throw new JeecgBootException("入库单状态非法");
        }
        //更改状态为提交审核
        inOrder.setStatus(WarehouseDictEnum.INBOUND_SUBMIT_AUDIT.getCode());
        this.updateById(inOrder);
    }

    @Override
    public IPage<WmsStockInOrders> pageList(Page<WmsStockInOrders> page, WmsStockInOrders wmsStockInOrders) {

        Page<WmsStockInOrders> result =wmsStockInOrdersMapper.pageLists(page, wmsStockInOrders) ;
        List<WmsStockInOrders> list = result.getRecords();


        //获取货主name
        list.stream().peek(item ->
                item.setOwnerName(iWmsCargoOwnersService.getById(item.getOwnerId()).getOwnerName())).toList();
        //获取仓库name
        list.stream().peek(item ->
                item.setWarehouseName(getWarehouseNameAndId().get(item.getWarehouseId()))).toList();
        result.setRecords(list);
        return result;
    }

    /**
     * 获取所有的仓库id和name的集合====>数据规模越大，就要考虑优化,用redis缓存
     *
     * @return 仓库名称和id
     */
    private Map<String, String> getWarehouseNameAndId() {
        List<WmsWarehouses> wmsWarehouses = wmsWarehousesMapper.selectList(Wrappers.emptyWrapper());
        return wmsWarehouses.stream().collect(Collectors.toMap(WmsWarehouses::getId, WmsWarehouses::getWarehouseName));
    }


    @Transactional
    @Override
    public void add(WmsStockInOrders wmsStockInOrders) {
        wmsStockInOrders.setOrderNumber(generateInOrderNo());
        wmsStockInOrders.setStatus(WarehouseDictEnum.INBOUND_INITIAL.getCode());
        wmsStockInOrdersMapper.insert(wmsStockInOrders);
    }

    /**
     * 生成入库单号
     *
     * @return code
     */
    private String generateInOrderNo() {
        //规则：ASN+8位年月日+4位序号
        String dateStr = DateUtils.now().substring(0, 10).replace("-", "");
        //redis自动生成序号
        long incr = 0;
        try {
            incr = redisUtil.incr("wms:asn_number" + dateStr, 1);
            if (incr == 1) {
                redisUtil.expire("wms:asn_number", 24 * 60 * 60 + 60);//加60秒，防止时间出现误差
            }
        } catch (Exception e) {
            throw new JeecgBootException("生成入库单号失败");
        }
        return "ASN" + dateStr + String.format("%04d", incr);
    }
    @Autowired
    private IWmsStockInOrderItemsService wmsStockInOrderItemsService;
    @Autowired
    private IWmsProductsService wmsProductsService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMain(WmsStockInOrdersPage wmsStockInOrdersPage) {
        WmsStockInOrders wmsStockInOrders = this.getOne(new QueryWrapper<WmsStockInOrders>().lambda().eq(WmsStockInOrders::getOrderNumber, wmsStockInOrdersPage.getOrderNumber()));
        if (Objects.isNull(wmsStockInOrders)){
            throw new JeecgBootException("入库单不存在");
        }
        String status = wmsStockInOrdersPage.getStatus();
        if (!WarehouseDictEnum.INBOUND_INITIAL.getCode().equals(status)&&!WarehouseDictEnum.INBOUND_REJECTED.getCode().equals(status)){
            throw new JeecgBootException("入库单状态非法");
        }
        List<WmsStockInOrderItems> itemsList = wmsStockInOrdersPage.getWmsStockInOrderItemsList();
        if (Objects.isNull(itemsList)){
            throw new JeecgBootException("入库明细不得为空");
        }

        //更新入库明细表
        //定义采购预期总数量
        int totalExpectedQuantity = 0;
        //按照入库批量删除
        wmsStockInOrderItemsService.remove(new QueryWrapper<WmsStockInOrderItems>().lambda().eq(WmsStockInOrderItems::getOrderId,wmsStockInOrders.getId()));

        Map<String,List<WmsStockInOrderItems>> groupingByItemsId=itemsList.stream().collect(Collectors.groupingBy(WmsStockInOrderItems::getProductId));
        List<WmsStockInOrderItems> merge =new ArrayList<>();

        groupingByItemsId.forEach((key, value) -> {
            WmsStockInOrderItems wmsStockInOrderItems;
            if (value.size() > 1) {
                int sum = value.stream().mapToInt(WmsStockInOrderItems::getExpectedQuantity).sum();
                wmsStockInOrderItems = new WmsStockInOrderItems();
                BeanUtil.copyProperties(value.get(0), wmsStockInOrderItems);
                wmsStockInOrderItems.setExpectedQuantity(sum);
                wmsStockInOrderItems.setOrderId(wmsStockInOrders.getId());
                //状态为初始
                wmsStockInOrderItems.setStatus(WarehouseDictEnum.INBOUND_INITIAL.getCode());
                //商品名称
                wmsStockInOrderItems.setProductName(wmsProductsService.getById(wmsStockInOrderItems.getProductId()).getProductName());
                merge.add(wmsStockInOrderItems);
            } else {
                wmsStockInOrderItems = value.get(0);
                wmsStockInOrderItems.setStatus(WarehouseDictEnum.INBOUND_INITIAL.getCode());
                wmsStockInOrderItems.setOrderId(wmsStockInOrders.getId());
                wmsStockInOrderItems.setProductName(wmsProductsService.getById(wmsStockInOrderItems.getProductId()).getProductName());
                merge.add(wmsStockInOrderItems);
            }
        });
        //赋值预期总量/submitAudit
        totalExpectedQuantity = merge.stream().mapToInt(WmsStockInOrderItems::getExpectedQuantity).sum();
       this.wmsStockInOrderItemsService.saveBatch(merge);

       WmsStockInOrders entity=BeanUtil.toBean(wmsStockInOrdersPage, WmsStockInOrders.class);
       entity.setTotalExpectedQuantity(totalExpectedQuantity);
       wmsStockInOrdersMapper.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delMain(String id) {
        wmsStockInOrderItemsMapper.deleteByMainId(id);
        wmsStockInOrdersMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delBatchMain(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            wmsStockInOrderItemsMapper.deleteByMainId(id.toString());
            wmsStockInOrdersMapper.deleteById(id);
        }
    }

}
